package ai.people.platform.archives.service.impl;

import ai.people.netmon.framework.domain.archives.entity.InformationBehavior;
import ai.people.netmon.framework.domain.archives.entity.InformationScoreDetails;
import ai.people.netmon.framework.exception.enums.InformationSearchExceptionEnum;
import ai.people.netmon.framework.exception.enums.ParamExceptionEnum;
import ai.people.netmon.framework.exception.type.BusinessException;
import ai.people.platform.archives.mapper.InformationAccountMapper;
import ai.people.platform.archives.service.InformationAccountService;
import ai.people.platform.archives.service.InformationBehaviorService;
import ai.people.platform.archives.service.InformationScoreDetailsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ai.people.netmon.framework.domain.archives.entity.InformationAccount;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author ligua
 * @description 针对表【information_account(信息查询用户行为记录表)】的数据库操作Service实现
 * @createDate 2022-06-06 16:11:38
 */
@Slf4j
@Service
public class InformationAccountServiceImpl extends ServiceImpl<InformationAccountMapper, InformationAccount>
        implements InformationAccountService {

    @Resource
    private InformationAccountMapper informationAccountMapper;

    @Resource
    private InformationScoreDetailsService informationScoreDetailsService;

    @Resource
    private InformationBehaviorService informationBehaviorService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 支付积分
     *
     * @param userId     用户id
     * @param behaviorId 行为id
     * @param dataId     数据标识
     * @param dataSource 数据源
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int payScore(Long userId, Long behaviorId, String dataId, String dataSource, String extJson) {
        if (userId == null || behaviorId == null) {
            throw new BusinessException(ParamExceptionEnum.INSUFFICIENT_PARAMETERS);
        }
        RLock lock = redissonClient.getLock("information::pay::score::lock::" + userId);
        try {
            if (lock.tryLock(3, TimeUnit.SECONDS)) {
                InformationBehavior behavior = informationBehaviorService.getById(behaviorId);
                if (behavior == null) {
                    throw new BusinessException(InformationSearchExceptionEnum.ILLEGAL_BEHAVIOR);
                }
                Long score = behavior.getScore();
                if(score <= 0){
                    //当前行为无需扣除积分
                    return 0;
                }

                if(StringUtils.isNotBlank(dataId) && dataSource != null){
                    //校验是否支付过
                    InformationScoreDetails one = informationScoreDetailsService.getOne(new LambdaQueryWrapper<InformationScoreDetails>()
                            .eq(InformationScoreDetails::getUserId, userId)
                            .eq(InformationScoreDetails::getBehaviorId, behaviorId)
                            .eq(InformationScoreDetails::getType, 0)
                            .eq(InformationScoreDetails::getDataId, dataId)
                            .eq(InformationScoreDetails::getDataSource, dataSource)
                            .eq(InformationScoreDetails::getIsDelete, 0));
                    if (one != null) {
                        //已经支付过，无需再次支付
                        return 1;
                    }
                }

                InformationAccount informationAccount = informationAccountMapper.selectOne(new QueryWrapper<InformationAccount>()
                        .lambda()
                        .eq(InformationAccount::getUserId, userId)
                        .eq(InformationAccount::getIsDelete, 0));
                if (informationAccount != null && informationAccount.getAvailableScore() >= score) {
                    int i = informationAccountMapper.payScore(userId, score);
                    if (i > 0) {
                        InformationScoreDetails scoreDetails = new InformationScoreDetails();
                        scoreDetails.setUserId(userId);
                        scoreDetails.setBehaviorId(behaviorId);
                        scoreDetails.setScore(score);
                        scoreDetails.setType(0);
                        scoreDetails.setCreateTime(new Date());
                        scoreDetails.setTs(new Date());
                        scoreDetails.setIsDelete(0);
                        scoreDetails.setDataId(dataId);
                        scoreDetails.setDataSource(dataSource);
                        scoreDetails.setExplain(extJson);
                        return informationScoreDetailsService.save(scoreDetails) ? 0 : -1;
                    }
                }
                throw new BusinessException(InformationSearchExceptionEnum.INSUFFICIENT_SCORE);
            }
        } catch (BusinessException e) {
            throw e;
        } catch (InterruptedException e) {
            log.error("Interrupted! 当前等待的线程被中止", e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("积分减扣失败，userId:{}, behaviorId:{}, dataId:{}, dataSource:{}",userId, behaviorId, dataId, dataSource);
            throw new BusinessException(InformationSearchExceptionEnum.INFORMATION_SEARCH_ERROR);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return -1;
    }
}




